#ifndef _SECUENCIAL_H_
#define _SECUENCIAL_H_

/********************************************************************
 * Secuencial.h
 * 
 * Descripcion :Esta clase representa un archivo de datos que almacena
 * los mismos en forma secuencial, sin utilizar un indice.
*********************************************************************/

#include "arch_datos.h"
#include "arch_espacios_libres.h"
#include "header.h"

#define EXT_EELL ".esp"
#define TAM_EELL 16

class Secuencial : public ArchivoDatos {
	//Atributos del archivo secuencial
	private:
		
		ArchEspaciosLibres* espacios_libres; //Referencia al archivo de espacios libres
		//Constructor de copia privado para que no se pueda copiar un archivo
		Secuencial(Secuencial &s);
	
	public:
	
		Secuencial(std::string& nombre, unsigned int tam_bloque);
	
		~Secuencial();
	
		//Metodos heredados de la interfaz de archivo
		
		void abrir() throw(ExcepAbriendoArch);
				
		void crear(std::string formato) throw(ExcepCreandoArch, ExcepSintaxisParser, ExcepBloqueTam); 
		
		void cerrar();
		
		void ingresar(TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegExistente, ExcepBloqueTam);
		
		void quitar(std::vector<ParesDatos*> &elementos, std::vector<TipoStruct*> &resultado) throw(ExcepArchCerrado);
		
		void consultar(std::vector<ParesDatos*> &consultas, std::vector<TipoStruct*> &resultado)
									 throw(ExcepArchCerrado,ExcepLeerBloque);
 		
 		void actualizar(TipoStruct * reg) throw(ExcepArchCerrado,ExcepRegInexistente, ExcepBloqueTam);
 													
 		TiposArchivo get_tipo_archivo();		
 		
 		void eliminar ();		
 		
 		/*
 		 * Devuelve el tamanio libre del archivo en cantidad de bytes.
 		 */
 		unsigned int get_espacio_libre() throw(ExcepArchCerrado, ExcepLeerBloque);
 		
 		/*
 		 * Devuelve la cantidad de registros en el archivo.
 		 */
 		unsigned int get_cant_regs() throw(ExcepArchCerrado);
 		
 		/*
		 * Devuelve el espacio libre en bytes del indice primario.
		 */ 
		virtual unsigned int get_esp_libre_indice()  throw(ExcepArchCerrado, ExcepLeerBloque);
		 
		/*
		 * Devuelve la cantidad de registros del indice primario.
		 */ 										
		virtual unsigned int get_cant_regs_indice() throw(ExcepArchCerrado);
		
		/*
 		 * Devuelve el tamanio ocupado total por el indice primario, en bytes.
 		 */ 
 		virtual long get_tam_arch_indice() throw(ExcepArchCerrado);
 		
 	//Metodos de uso interno del archivo secuencial	
 		
 	private:
		
		/*
		 * Dada una ref a un bloque, se encarga de obtener la cant de registros contenidos dentro
		 * del mismo.
		 */
		unsigned int get_cant_regs_bloque(Bloque* bloque);
		
		/*
		 * Dada una ref a un bloque y una cantidad de regs, actualiza la cant de regs en el mismo.
		 */
		void set_cant_regs_bloque(Bloque* bloque, unsigned int cant);	
		
		/*
		 * Dado un bloque, y la pos y tamanio de un reg, saca el reg del bloque y decrementa la cant
		 * de registros en el bloque.
		 */
		int sacar_reg_bloque(Bloque* bloque, TipoStruct * reg, unsigned int pos_reg, unsigned int tam_reg);
		
		/*
		 * Dados un bloque y un reg pasado por param, serializa el reg y lo pone en el bloque al final
		 * del mismo si este entra. De ser asi devuelve true.
		 * Si el reg no entra en el bloque devuelve false.
		 */
 		bool poner_reg_en_bloque(Bloque* bloque, TipoStruct* reg);

		/*
		 * Devuelve true si el reg pasado como param no esta en el archivo,
		 * false en caso contrario.
		 */		
		bool es_unico(TipoStruct * reg);
		
		
		
		/*
 		 * Devuelve true si dentro de las consultas se verifica q se esta buscando
 		 * por clave, false en caso contrario. 
 		 */
 		bool consulta_por_clave(std::vector<ParesDatos*> &consultas);
 		
 		/*
 		 * Si el bloque es el ultimo lo elimina del archivo.
 		 * Si no es el ultimo lo intercambia con este y lo elimina.
 		 */
 		void eliminar_bloque (Bloque* bloque);
 		
 		/*
 		 * Intercambia el contenido de los bloques 1 y 2.
 		 */
 		void intercambiar_bloque (unsigned int nbloque1, unsigned int nbloque2);
 		
 		/*
		 * Devuelve la primera posicion donde se encuentran los registros
		 * en el archivo, es decir, luego de los tags de control
		 */ 
		unsigned int get_primera_pos(){
			return sizeof(unsigned int);
		}
};

#endif
